package com.hyt.it.ogt.pj.data.mq;

import java.io.IOException;
import java.util.UUID;

import javax.annotation.Resource;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.hyt.it.ogt.pj.data.model.entity.kw.PushPj;
import com.hyt.it.ogt.pj.data.model.entity.pj.Project;
import com.hyt.it.ogt.pj.data.service.kw.IPushPjService;
import com.hyt.it.ogt.pj.data.service.pj.IProjectService;
import com.hyt.it.ogt.pj.data.utils.RedisLock;
import com.rabbitmq.client.Channel;

import lombok.extern.slf4j.Slf4j;

/**
 * 推送评卷数据消费者
 *
 * @author liuqi
 * @date 2022-05-31
 */
@Component
@Slf4j
public class PushPjDataConsumer {

    private final static String LOCK_KEY_HEAD = "INIT_PROJECT:";

    private final static int LOCK_TIME = 10;

    @Resource
    private IPushPjService iPushPjService;

    @Resource
    private IProjectService iProjectService;

    @Resource
    private RedisLock redisLock;

    @RabbitListener(
    		bindings = {@QueueBinding(value = @Queue( value = "${mq.pushPjData.queue}", 
    		autoDelete = "false",durable = "true"), 
    		exchange = @Exchange( value = "${mq.direct}",
    		type = ExchangeTypes.DIRECT),
            key = {"${mq.pushPjData.route}"})},
            concurrency = "${mq.pushPjData.concurrency}")
    public void pushPjDataListener(String json, Message message, Channel channel) throws IOException {
        log.info("消费推送评卷数据:【{}】", json);
        PushPj pushPj = JSON.parseObject(json, PushPj.class);
        Long pushId = pushPj.getId();
        String projectId = pushPj.getExamId();
        String officeId = pushPj.getOfficeId();
        String admissionNum = pushPj.getAdmissionNum();
        //1.初始化评卷项目
        Project project = iProjectService.getById(projectId);
        if (project == null) {
            //获取初始化项目锁
            String key = LOCK_KEY_HEAD + projectId;
            String consumerId = UUID.randomUUID().toString();
            boolean lockSuccess = redisLock.tryLock(key, consumerId, LOCK_TIME);
            if (lockSuccess) {
                //获取锁成功，执行初始化项目
                try {
                    iProjectService.initProjectForTask(projectId, officeId);
                } catch (Exception e) {
                    log.error("初始化评卷项目异常:", e);
                    //评卷项目初始化异常，推送任务改为初始化异常状态
                    iPushPjService.updateStatus(pushId, 2, e.getMessage());
                    channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                    return;
                } finally {
                    //释放锁
                    redisLock.unLock(key, consumerId);
                }
            } else {
                //评卷项目正在其它消费者初始化，推送任务改为未推送状态，等待下一轮定时任务推送
                iPushPjService.updateStatus(pushId, 0);
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                return;
            }
        } else {
        	iProjectService.updateProjectForTask(projectId, officeId);
        }
        
        //2.推送考生评卷数据
        try {
            iProjectService.addProjectStudentForTask(projectId, officeId, admissionNum);
            //删除记录
            iPushPjService.delete(pushId);
        } catch (Exception e) {
            log.error("推送考生评卷数据异常:", e);
            iPushPjService.updateStatus(pushId, 2, e.getMessage());
        } finally {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }
    }

}
